package com.ruoyi.common.utils;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.ruoyi.common.utils.sign.Md5Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.servlet.http.HttpServletRequest;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.text.ParseException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class CurrencyUtil {

	private static final Logger logger = LoggerFactory.getLogger(CurrencyUtil.class);

	public static String getRemoteAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");  
        if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {  
            ip = request.getHeader("Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {  
            ip = request.getRemoteAddr();  
        }  
        return ip;  
    }
	
	public static String createSign(SortedMap<String, String> smap, String paykey){
        StringBuffer sb = new StringBuffer();
        for(String k : smap.keySet()){
        	String v = smap.get(k);
			if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
        }
        sb.append("key=" + paykey);
        return Md5Utils.hash(sb.toString());
    }


	public static final int getProcessID() {
		RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
		return Integer.valueOf(runtimeMXBean.getName().split("@")[0])
				.intValue();
	}

	public static String runExec(String... cmd) throws Exception{
		Process pro = Runtime.getRuntime().exec(cmd);
		pro.waitFor();
		InputStream in = pro.getInputStream();
		BufferedReader read = new BufferedReader(new InputStreamReader(in));
		return read.readLine();
	}

	public static List<String> getDynamicParams(String str){
		List<String> params = new ArrayList<>();
		Pattern p = Pattern.compile("\\[([^]]*)\\]");
		Matcher m = p.matcher(str);
		while (m.find()){
			String group = m.group(1);
			params.add(group);
		}
		return params;
	}

	public static boolean engineEvalbool(String str) {
		boolean booleanResult = false;
		try{
			ScriptEngineManager manager = new ScriptEngineManager();
			ScriptEngine engine = manager.getEngineByName("js");
			Object result = engine.eval(str);
			if (Boolean.class.getName().equals(result.getClass().getName())) {
				booleanResult = (Boolean) result;
			}
		}catch (Exception e){
			e.printStackTrace();
		}
		return booleanResult;
	}

	/**
	 * 获取json属性值
	 * @param jsonObject
	 * @param key  xx.xxx[1][0].xxxx
	 * @return
	 */
	public static Object readJson(JSONObject jsonObject, String key) {
		try {
			//分隔key
			String[] keys = key.split("\\.");
			Object val = jsonObject;
			for (int i = 0 ; i < keys.length ; i ++) {
				//需要判断是否为集合类型
				List<String> list = getDynamicParams(keys[i]);
				if(list.size() > 0){
					String aKey = keys[i].substring(0, keys[i].indexOf("["));
					for (int j = 0; j < list.size(); j++) {
						int ki = Integer.parseInt(list.get(j));
						if(val.getClass().getName().contains("JSONObject")){
							val = ((JSONObject) val).getJSONArray(aKey).get(ki);
						}else if(val.getClass().getName().contains("JSONArray")){
							val = ((JSONArray) val).get(ki);
						}
					}
				}else {
					val = ((JSONObject) val).get(keys[i]);
				}
				//判断是否为最后一个属性
				if(i == keys.length - 1){
					return val;
				}
			}
		}catch (Exception e){
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 按位判断 1表示true 0表示false
	 * @param flag
	 * @param per
	 * @return
	 */
	public static boolean isAllow(int flag, int per){
		return ((flag&per) == per);
	}


	public static String getDifSet(String mores, String lesss) {
		if (StringUtils.isEmpty(mores)) mores = "";
		if (StringUtils.isEmpty(lesss)) lesss = "";
		String[] more = mores.split(",");
		String[] less = lesss.split(",");
		if (StringUtils.isEmpty(mores)) return lesss;
		if (StringUtils.isEmpty(lesss)) return mores;

		//将多转换为set fid 肯定不是小的
		Set<String> set = new HashSet<String>(Arrays.asList(more));
		for (String p : less) {
			// 如果集合里有相同的就删掉，如果没有就将值添加到集合
			if (set.contains(p)) {
				set.remove(p);
			} else {
				set.add(p);
			}
		}
		return StringUtils.join(set.toArray(), ",");
	}

	public static String getDifSetUnion(String mores, String lesss) {
		if (StringUtils.isEmpty(mores)) mores = "";
		if (StringUtils.isEmpty(lesss)) lesss = "";
		String[] more = mores.split(",");
		String[] less = lesss.split(",");
		if (StringUtils.isEmpty(mores)) return lesss;
		if (StringUtils.isEmpty(lesss)) return mores;

		//将多转换为set fid 肯定不是小的
		Set<String> set = new HashSet<String>(Arrays.asList(more));
		for (String p : less) {
			set.add(p);
		}
		for (String p : more) {
			set.add(p);
		}
		return StringUtils.join(set.toArray(), ",");
	}

	public static List<Long> stringToLongList(String strArr) {
		if (StringUtils.isEmpty(strArr)) return null;
		return Arrays.stream(strArr.split(","))
				.map(s -> Long.parseLong(s.trim()))
				.collect(Collectors.toList());
	}


	public static String execCmd(String command){

		try {
			logger.info("执行本地命令："+command);
			// 执行命令
			Process process = Runtime.getRuntime().exec(new String[]{"sh", "-c", command});

			BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
			StringBuilder output = new StringBuilder();
			String line;
			while ((line = reader.readLine()) != null) {
				output.append(line).append("\n");
			}

			// 等待进程执行完成
			int exitCode = process.waitFor();

			// 打印转录文本
			String response = output.toString();
			logger.info("执行本地命令【"+exitCode+"】结果："+response);
			return response;
		}catch (Exception e){
			e.printStackTrace();
		}
		return null;
	}

	public static String remoteExecCmd(String host, String user, String password, String command, String charset){
		StringBuffer sb = new StringBuffer();
		try {
			logger.info("远程调用IP："+host+"，执行指令："+command);
			JSch jsch = new JSch();

//            jsch.setLogger(new MyLogger());

			Session session = jsch.getSession(user, host, 22);
			session.setTimeout(30000);
			session.setPassword(password);
			session.setConfig("StrictHostKeyChecking", "no");
//            session.setConfig("PreferredAuthentications", "publickey,password");
//            session.setConfig("shell", "cmd.exe");
			session.connect();

			ChannelExec channel = (ChannelExec) session.openChannel("exec");
			channel.setCommand(command);

			InputStream in = channel.getInputStream();
			channel.connect();

//            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
//            String line;
//            while ((line = reader.readLine()) != null) {
//                System.out.println(new String(line.getBytes(), charset));
//            }

			byte[] buffer = new byte[65535];
			while (in.read(buffer) != -1) {
				sb.append(new String(buffer, charset));
			}

			channel.disconnect();
			session.disconnect();
		} catch (JSchException | IOException e) {
			e.printStackTrace();
			return "error";
		}
		logger.info("远程调用IP："+host+"，执行结果："+sb.toString());
		return sb.toString();
	}
	public static String remoteExecCmd(String host, String user, String password, String command){
		return remoteExecCmd(host, user, password, command, "GBK");
	}


//	public static String hutoolEncode(String str, String salt){
//		if (StringUtils.isEmpty(str)) return null;
//		AES aes = SecureUtil.aes(salt.getBytes());
//		return aes.encryptHex(str);
//	}
//
//	public static String hutoolDecode(String str, String salt){
//		if (StringUtils.isEmpty(str)) return null;
//		AES aes = SecureUtil.aes(salt.getBytes());
//		return aes.decryptStr(str);
//	}

	public static String create(int scFor) {
		String[] a2 = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
		Random r = new Random();
		String result = "";
		while (result.length() < scFor) {
			int temp = r.nextInt(a2.length);
			result = result + a2[temp];
		}
		return result;
	}

	public static String htmlTotext(String html) {
		Document doc = Jsoup.parse(html);
		Element body = doc.body();
		return body.text();
	}

	public static void mergeAudioFiles(String[] audioFiles, String outputFilePath) throws Exception {
		AudioInputStream mergedStream = null;

		for (String filePath : audioFiles) {
			AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(filePath));

			// 读取第一个文件格式
			if (mergedStream == null) {
				mergedStream = audioInputStream;
			} else {
				// 检查格式是否一致
				if (!AudioSystem.isConversionSupported(mergedStream.getFormat(), audioInputStream.getFormat())) {
					audioInputStream = AudioSystem.getAudioInputStream(mergedStream.getFormat(), audioInputStream);
				}
				mergedStream = new AudioInputStream(
						new SequenceInputStream(mergedStream, audioInputStream),
						mergedStream.getFormat(),
						mergedStream.getFrameLength() + audioInputStream.getFrameLength()
				);
			}
		}

		// 将合成后的音频流写入文件
		AudioSystem.write(mergedStream, AudioFileFormat.Type.WAVE, new File(outputFilePath));

		// 关闭音频流
		if (mergedStream != null) {
			mergedStream.close();
		}
	}


	// 方法1：基本执行（同步阻塞）
	public static String executeCommand(String command) throws IOException {
		StringBuilder output = new StringBuilder();
		Process process = Runtime.getRuntime().exec(command);

		try (BufferedReader reader = new BufferedReader(
				new InputStreamReader(process.getInputStream()))) {
			String line;
			while ((line = reader.readLine()) != null) {
				output.append(line).append("\n");
			}
		}

		return output.toString();
	}

	// 方法2：带环境变量的执行
	public static String executeWithEnv(String[] command, String[] envp) throws IOException {
		Process process = Runtime.getRuntime().exec(command, envp);
		return readProcessOutput(process);
	}

	// 方法3：使用ProcessBuilder（推荐）
	public static String executeWithProcessBuilder(String... command) throws IOException {
		ProcessBuilder builder = new ProcessBuilder(command);
		builder.redirectErrorStream(true); // 合并错误流和输出流
		Process process = builder.start();
		return readProcessOutput(process);
	}

	private static String readProcessOutput(Process process) throws IOException {
		StringBuilder output = new StringBuilder();
		try (BufferedReader reader = new BufferedReader(
				new InputStreamReader(process.getInputStream()))) {
			String line;
			while ((line = reader.readLine()) != null) {
				output.append(line).append("\n");
			}
		}
		return output.toString();
	}

	public static void main(String[] args) throws Exception {

//		long start = System.currentTimeMillis();
//		String s = remoteExecCmd("45.204.146.75", "root", "e4%qR1x5@Ca6Wb", "python3 /home/test/q.py http://oramemo.szcclg.com/111.m4a", "utf-8");
////		String s = remoteExecCmd("45.204.146.75", "root", "e4%qR1x5@Ca6Wb", "python3 /home/test/q.py /home/test/111.m4a", "utf-8");
//
//		System.out.println(s);
//		System.out.println("耗时："+(System.currentTimeMillis() - start));


		mergeAudioFiles(new String[]{"D:\\111.wav", "D:\\222.wav", "D:\\1.wav"}, "D:\\3.wav");

	}

}
